
from datetime import datetime as dt
from google.appengine.ext import db
from models.BaoCaoDoanhThu import BaoCaoDoanhThu
from models.ChiTietDonHang import ChiTietDonHang
from models.ChiTieuKinhDoanh import ChiTieuKinhDoanh
from models.DonHang import DonHang
from models.GiaBan import GiaBan
from models.HangDatHomNay import HangDatHomNay
from models.HangHoa import HangHoa
from models.HoaHongNhanVien import HoaHongNhanVien
from models.KhachHang import KhachHang
from models.LoaiNhanVien import LoaiNhanVien
from models.NhanVien import NhanVien
from models.PhanQuyen import PhanQuyen
from models.ThuChi import ThuChi
from utils.Const import TrangThaiDonHang, TrangThaiGiaBan
import datetime
import utils.Const

class DaoQuanLyNhanVien():
    
    @staticmethod
    def createOrUpdateNhanVien(nhanVien):
        key = nhanVien.put()
        DaoQuanLyNhanVien.addPermForStaffByType(nhanVien.loaiNV, key.id())
    
    @staticmethod
    def deleteNhanVien(nhanVien):
        nhanVien.delete()
        
    @staticmethod
    def deleteHangHoa(hh):
        hh.delete()
    
    @staticmethod
    def deleteDonHang(maDonHang):
        dh = DaoQuanLyNhanVien.getDonHangById(maDonHang)
        if dh.trangThai in [TrangThaiDonHang.DANG_DAT_HANG, TrangThaiDonHang.DA_DAT_HANG]:
            dh.delete()
            query = ChiTietDonHang.all().filter('maDonHang =', int(maDonHang)).fetch(10000, 0)
            db.delete(query)
    
    @staticmethod
    def listObjectToListDict(lstObj, clazz):
        items = []
        for item in lstObj:
            temp = {}
            for key, _ in clazz.properties().iteritems():
                value = getattr(item, key)
                if value.__class__ == datetime.datetime or value.__class__ == datetime.date:
                    temp[key] = value.strftime('%d/%m/%Y')
                else:
                    temp[key] = value
            temp['id'] = item.key().id()
            items.append(temp)
        return items
    
    @staticmethod
    def getListNhanVien(tenNV, loaiNV, gridRowNum, begin, parentId):
        query = NhanVien.all()
        if tenNV != '':
            query.filter('tenNV =', tenNV)
        if loaiNV != '':
            query.filter('loaiNV =', int(loaiNV))
        if parentId != '':
            query.filter('parentId =', int(parentId))
        rs = query.fetch(gridRowNum, begin)
        if parentId != '':
            rs.append(DaoQuanLyNhanVien.getNhanVienById(int(parentId)))
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, NhanVien)
        return items, query.count()
    
    @staticmethod
    def getListThuChi(fromDate, toDate, gridRowNum, begin):
        query = ThuChi.all();
        if fromDate != '':
            query.filter('ngay >=', dt.strptime(fromDate, '%d/%m/%Y').date())
        if toDate != '':
            query.filter('ngay <=', dt.strptime(toDate, '%d/%m/%Y').date())
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, ThuChi)
        return items, query.count()
    
    @staticmethod
    def updateThuChi(thuChi):
        thuChi.put()
    
    @staticmethod
    def getListChiTietDonHang(maDonHang, gridRowNum, begin):
        query = ChiTietDonHang.all().filter('maDonHang =', int(maDonHang))
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, ChiTietDonHang)
        for item in items:
            item['hangHoa'] = str(item['maHang']) + ' - ' + item['tenHang']
        return items, query.count()
    
    @staticmethod
    def getListDonHang(maKhachHang, tuNgay, denNgay, gridRowNum, begin, maNV, ngayGiao):
        
        query = DonHang.all()
        
        denNgayDate = None
        
        if ngayGiao != '':
            query.filter('ngayGiao1 =', dt.strptime(ngayGiao, '%d/%m/%Y').date())
        
        if tuNgay != '':
            query.filter('ngayDat >=', dt.strptime(tuNgay, '%d/%m/%Y').date())
        if denNgay != '':
            query.filter('ngayDat <=', dt.strptime(denNgay, '%d/%m/%Y').date())
        
        if maKhachHang != '':
            query.filter('maKH =', int(maKhachHang))
        elif maNV != '':
            lstNV,_ = DaoQuanLyNhanVien.getListNhanVien('', '', 10000, 0, int(maNV))
            lst = []
            for nv in lstNV:
                lst.append(nv['id'])
            query.filter('maNVDat in', lst)
        if tuNgay != '' or denNgay != '':
            query.order('-ngayDat')
        
        query.order('-ngayGiao1')
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, DonHang)
        
        temp = []
        for item in items:
            if item['trangThai'] != TrangThaiDonHang.DANG_DAT_HANG:
                temp.append(item)
        items = temp
            
        for item in items:
            maKH = item['maKH']
            duTru = item['duTru']
            if maKH is not None:
                if duTru == True:
                    item['khachHang'] = 'Du tru - ' + DaoQuanLyNhanVien.getNhanVienById(maKH).tenNV
                else:
                    item['khachHang'] = str(maKH) + ' - ' + DaoQuanLyNhanVien.getKhachHangById(maKH).tenKhachHang
            tenNVGiaoHang = item['tenNVGiaoHang']
            if tenNVGiaoHang != None:
                item['nguoiGiao'] = str(item['maNVGiaoHang']) + ' - ' + item['tenNVGiaoHang']
            try:
                item['conLai'] = item['tongTien'] - item['tienDaThanhToan']
            except:
                pass
            item['chiTiet'] = "<a href='/donhang/?id=" + str(item['id']) + "'>Chi tiet</a>"
        return items, query.count()
    
    @staticmethod
    def deleteChiTietDonHang(ctdh):
        ctdh.delete()
        
    @staticmethod
    def createOrUpdateChiTietDonHang(ctdh):
        ctdh.put()
    
    @staticmethod
    def getListLoaiNhanVien():
        rs = LoaiNhanVien.all()
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, LoaiNhanVien)
        return items
    
    @staticmethod
    def getAllKhachHang(maNV):
        lstNV,_ = DaoQuanLyNhanVien.getListNhanVien('', '', 10000, 0, maNV)
        rs = []
        for nv in lstNV:
            rs += KhachHang.all().filter('maNV =', int(nv['id']))
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, KhachHang)
        return items
    
    @staticmethod
    def getAllHangHoa():
        query = HangHoa.all()
        query.order('-tenHangHoa')
        rs = query.fetch(10000, 0)
        return DaoQuanLyNhanVien.listObjectToListDict(rs, HangHoa)
    
    @staticmethod
    def getListKhachHang(maNV, gridRowNum, begin, parentId):
        query = KhachHang.all()
        if maNV != '':
            query.filter('maNV =', long(maNV))
        if parentId != '':
            lstNV = []
            lstFullNV,_ = DaoQuanLyNhanVien.getListNhanVien('', '', 10000, 0, parentId)
            for nv in lstFullNV:
                lstNV.append(nv['id'])
            query.filter('maNV in', lstNV)    
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, KhachHang)
        return items, query.count()
    
    @staticmethod
    def getListCongNo(maKH, gridRowNum, begin, sortBy):
        if maKH != '':
            kh = DaoQuanLyNhanVien.getKhachHangById(long(maKH))
            return DaoQuanLyNhanVien.listObjectToListDict([kh], KhachHang), 1
        
        query = KhachHang.all()
        query.filter('congNo >', 0.0)
        if sortBy == 'asc':
            query.order('congNo')
        else:
            query.order('-congNo')
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, KhachHang)
        return items, query.count()
    
    @staticmethod
    def getListChiTieuKinhDoanh(maNV, thang, nam, gridRowNum, begin):
        query = ChiTieuKinhDoanh.all()
        if maNV != '':
            query.filter('maNV =', int(maNV))
        if thang != '':
            query.filter('thang =', int(thang))
        if nam != '':
            query.filter('nam =', int(nam))
        
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, ChiTieuKinhDoanh)
        return items, query.count()
    
    @staticmethod
    def deleteHoaHongNhanVien(hoaHongNhanVien):
        hoaHongNhanVien.delete()
    
    @staticmethod
    def getListHoaHongNhanVien(maNV, gridRowNum, begin):
        query = HoaHongNhanVien.all().order('nhoNhat')
        query.filter('maNV =', int(maNV))
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, HoaHongNhanVien)
        return items, query.count()
    
    @staticmethod
    def createOrUpdateHoaHongNhanVien(hhnv):
        hhnv.put()
    
    @staticmethod
    def createOrUpdateChiTieuKinhDoanh(chiTieuKinhDoanh):
        chiTieuKinhDoanh.put()
    
    @staticmethod
    def createOrUpdateKhachHang(kh):
        kh.put()
        
    @staticmethod
    def createOrUpdateHangHoa(hh):
        hh.put()
    
    @staticmethod
    def deleteChiTieuKinhDoanh(chiTieuKinhDoanh):
        chiTieuKinhDoanh.delete()
        
    @staticmethod
    def deleteKhachHang(kh):
        kh.delete()
    
    @staticmethod
    def updateTenNhanVien(nhanVienId, tenMoi):
        query = ChiTieuKinhDoanh.all()
        query.filter('maNV =', int(nhanVienId))
        items = []
        for item in query:
            item.tenNV = tenMoi
            items.append(item)
            
        query = BaoCaoDoanhThu.all()
        query.filter('maNV =', int(nhanVienId))
        for item in query:
            item.tenNV = tenMoi
            items.append(item)
            
        query = NhanVien.all()
        query.filter('parentId =', int(nhanVienId))
        for item in query:
            item.parentName = tenMoi
            items.append(item)
            
        query = HoaHongNhanVien.all()
        query.filter('maNV =', int(nhanVienId))
        for item in query:
            item.tenNV = tenMoi
            items.append(item)
            
        query = DonHang.all()
        query.filter('maNVGiaoHang =', int(nhanVienId))
        for item in query:
            item.tenNVGiaoHang = tenMoi
            items.append(item)
        
        query = ChiTieuKinhDoanh.all()
        query.filter('maNV =', int(nhanVienId))
        for item in query:
            item.tenNV = tenMoi
            items.append(item)
            
        query = DonHang.all()
        query.filter('maNVDat =', int(nhanVienId))
        for item in query:
            item.tenNVDat = tenMoi
            items.append(item)
        
        query = KhachHang.all()
        query.filter('maNVGiaoHang =', int(nhanVienId))
        for item in query:
            item.tenNVGiaoHang = tenMoi
            items.append(item)
        
        db.put(items)
    
    @staticmethod
    def updateTenHangHoa(hangHoaId, tenMoi):
        query = HangDatHomNay.all()
        query.filter('maHang =', int(hangHoaId))
        items = []
        for item in query:
            item.tenHang = tenMoi
            items.append(item)
        
        query = GiaBan.all()
        query.filter('maHangHoa =', int(hangHoaId))
        items = []
        for item in query:
            item.tenHangHoa = tenMoi
            items.append(item)
        
        query = ChiTietDonHang.all()
        query.filter('maHang =', int(hangHoaId))
        items = []
        for item in query:
            item.tenHang = tenMoi
            items.append(item)
        
        db.put(items)
                    
    @staticmethod
    def getNhanVienById(id):
        return NhanVien.get_by_id(id, None)
    
    @staticmethod
    def getLoaiNhanVienById(id):
        return LoaiNhanVien.get_by_id(id, None)
    
    @staticmethod
    def getHangHoaById(id):
        return HangHoa.get_by_id(id, None)
    
    @staticmethod
    def getKhachHangById(id):
        return KhachHang.get_by_id(id, None)

    @staticmethod
    def getDonHangById(id):
        return DonHang.get_by_id(id, None)
    
    @staticmethod
    def getListHangHoa(id, gridRowNum, begin):
        query = HangHoa.all()
        if id != '':
            q = []
            q.append(HangHoa.get_by_id(int(id), None))
            items = DaoQuanLyNhanVien.listObjectToListDict(q, HangHoa)
            return items, 1
        query.order('-tenHangHoa')
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, HangHoa)
        return items, query.count()

    @staticmethod
    def getListHangSanXuatHomNay(ngay, gridRowNum, begin):
        query = HangDatHomNay.all().filter('ngay =', ngay)
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, HangDatHomNay)
        for item in items:
            item['soLuongCanSanXuatThem'] = item['soLuongDat'] + 2*item['duTru'] - item['soLuongTonKho']
        return items, query.count()
    
    @staticmethod
    def getListGiaBan(maKhachHang, maHangHoa, gridRowNum, begin):
        query = GiaBan.all()
        if maKhachHang != '':
            query.filter('maKhachHang =', int(maKhachHang))
        if maHangHoa != '':
            query.filter('maHangHoa =', int(maHangHoa))
        
        rs = query.fetch(gridRowNum, begin)
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, GiaBan)
        return items, query.count()
    
    @staticmethod
    def getGiaBan(maKhachHang, maHangHoa):
        query = GiaBan.all()
        query.filter('maKhachHang =', int(maKhachHang)).filter('maHangHoa =', int(maHangHoa))
        query.filter('trangThai =', TrangThaiGiaBan.DUYET)
        query.order('-ngayBatDau')
        
        rs = query.fetch(1, 0)
        if rs.__len__() == 0:
            return DaoQuanLyNhanVien.getHangHoaById(maHangHoa).giaMacDinh
        else:
            return rs[0].giaBan
    
    @staticmethod
    def createOrUpdateGiaBan(gb):
        gb.put()
    
    @staticmethod
    def createOrUpdateDonHang(dh):
        dh.put()
        
    @staticmethod
    def deleteGiaBan(gb):
        gb.delete()
    
    @staticmethod
    def getNhanVienByUsername(username):
        rs = NhanVien.all().filter('username =', username.lower())
        for item in rs:
            return item
        
    @staticmethod
    def getListStaffPriviledge(maNV):
        query = PhanQuyen.all().filter('maNV =', int(maNV))
        lst = query.run()
        rs = {}
        for item in lst:
            rs[item.func] = item.priv
        return rs
    
    @staticmethod
    def getAllFunctions():
        lstFunc = []
        lstMenu = utils.Const.Const.LIST_MENU
        lstOtherPriv = utils.Const.Const.OTHER_PRIV
        for key in lstMenu:
            for func in lstMenu[key]:
                lstFunc.append(key + '.' + func)
        for item in lstOtherPriv:
            lstFunc.append(item)
        return lstFunc
    
    @staticmethod
    def getStaffFunctions(ma, typeId):
        lstDeniedFunc = DaoQuanLyNhanVien.getAllFunctions()
        query = PhanQuyen.all().filter('maNV =', int(ma)).filter('typeId =', typeId)
        rs =query.run() 
        lstAllowedFunc = []
        for item in rs:
            try:
                lstAllowedFunc.append(item.func + '.' + item.priv)
                lstDeniedFunc.remove(item.func + '.' + item.priv)
            except:
                raise
        return lstAllowedFunc, lstDeniedFunc
    
    @staticmethod
    def getPhanQuyen(ma, typeId, func):
        query = PhanQuyen.all().filter('maNV =', int(ma)).filter('func =', func).filter('typeId =', int(typeId))
        pq = query.get()
        if pq == None:
            pq = PhanQuyen()
            pq.maNV = ma
            pq.typeId = typeId
            pq.func = func
            pq.menu = func[:func.find('.')]
        return pq
    
    @staticmethod
    def addPermForStaffByType(maLoaiNV, maNV):
        lstAllow = PhanQuyen.all().filter('maNV =', int(maLoaiNV)).filter('typeId =', utils.Const.Const.LOAI_NV)
        
        lstAllowStaff = PhanQuyen.all().filter('maNV =', int(maNV)).filter('typeId =', utils.Const.Const.NV)
        lstPQ = []
        for item in lstAllowStaff:
            lstPQ.append(item)
        db.delete(lstPQ)
        lstPQ = []
        for item in lstAllow:
            pq = PhanQuyen()
            pq.menu = item.menu
            pq.typeId = utils.Const.Const.NV
            pq.maNV = int(maNV)
            pq.func = item.func
            pq.priv = item.priv
            lstPQ.append(pq)
        db.put(lstPQ)
            
    
    @staticmethod
    def addAllPrivForManager():
        lstMenu = utils.Const.Const.LIST_MENU
        lstPQ = []
        for key in lstMenu:
            for func in lstMenu[key]:
                pq = DaoQuanLyNhanVien.getPhanQuyen(utils.Const.LoaiNhanVien.QUAN_LY, 1, key + '.' + func)
                pq.priv = 'Owner'
                lstPQ.append(pq)
        db.put(lstPQ)
        
    @staticmethod
    def getListDonHangByStatus(status):
        query = DonHang.all().filter('trangThai =', status)
        return query.run()
        
        
    @staticmethod
    def getListDoanhThu(idNV, idKH, fromDate, toDate, gridRowNum, begin):
        query = BaoCaoDoanhThu.all();
        if fromDate != '':
            query.filter('ngay >=', dt.strptime(fromDate, '%d/%m/%Y').date())
        if toDate != '':
            query.filter('ngay <=', dt.strptime(toDate, '%d/%m/%Y').date())
        if idNV != '':
            query.filter('maNV =', int(idNV))
        if idKH != '':
            query.filter('maKH =', int(idKH))
        
        #rs = query.fetch(gridRowNum, begin)
        
        query.order('ngay')
        rs = query.run()
        items = DaoQuanLyNhanVien.listObjectToListDict(rs, BaoCaoDoanhThu)
        items = sorted(items, key=lambda k: k['maNV']) 
        return items, query.count()
    
    @staticmethod
    def getDoanhThuByMaKhachHangAndNgay(idKH, ngay):
        query = BaoCaoDoanhThu.all();
        query.filter('maKH =', idKH)
        query.filter('ngay =', ngay)
        rs = query.get()
        if rs == None:
            rs = BaoCaoDoanhThu()
            rs.maKH = idKH
            kh = KhachHang.get_by_id(int(idKH))
            rs.tenKH = kh.tenKhachHang
            rs.maNV = kh.maNV
            rs.tenNV = NhanVien.get_by_id(kh.maNV).tenNV
            rs.ngay = ngay
            rs.doanhThu = 0.0
            rs.tongThu = 0.0
            rs.put()
        return rs
    
    @staticmethod
    def getChiTieuKinhDoanh(maNV):
        query = ChiTieuKinhDoanh.all();
        query.filter('maNV =', int(maNV))
        query.filter('thang =', dt.now().month)
        query.filter('nam =', dt.now().year)
        rs = query.get()
        if rs == None:
            return 0
        return rs.doanhSo